home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / pdclk139.zip / IP.ASM < prev    next >
Assembly Source File  |  1992-05-17  |  55KB  |  2,314 lines

  1. ;        ip.asm
  2. ;========================================================================
  3.  
  4. ; Copyright (C) 1991 by Jan.Engvald@ldc.lu.se, see file COPYING.
  5.  
  6. ;************************************************************************
  7. ;************************************************************************
  8. ;*
  9. ;*        UDP/IP library
  10. ;*
  11. ;* This library is in a transition phase from a PDCLKSET specific library
  12. ;* into a multiprocess, reentrant, any hardware type, general UDP/IP
  13. ;* library. The buffers used have a descriptor part and a packet part.
  14. ;* The descriptor part is used to allow reentrancy, different physical 
  15. ;* address lengths and varying number of IP options.
  16. ;*
  17. ;* In this library DS:BX always points to the descriptor buffer, DS:DI
  18. ;* usually points to the physical header/IP header/UDP header part of
  19. ;* the IP packet buffer and DX,AX often contains an IP number in network
  20. ;* byte order (DL,DH,AL,AH). For efficiency reasons, IP numbers are
  21. ;* searched last half first (first halves are often equal).
  22. ;*
  23. ;* As this library is still evolving, you can not assume that it looks
  24. ;* the same in the next release. In particular, if you are using any of
  25. ;* of the subroutines, check if their calls or results have been changed.
  26. ;*
  27. ;* The current implementation is RFC791 (IP) and RFC1122 (host requirements)
  28. ;* compliant, except for a few cases: I havn't found a reasonable solution
  29. ;* on how to report back to the application ICMP errors like parameter
  30. ;* problem, protocol and port unreachables, and fragment reassembly time
  31. ;* exceeded. Also, IP options are allowed, but the interpretation and handling
  32. ;* must be done by the application. Apart from the above, it is a de luxe
  33. ;* implementation that includes things like multiple default gateways,
  34. ;* sending protocol and port unreachables, IP type of service handling (not
  35. ;* tested), fragment reassembly and source quench introduced delay.
  36. ;*
  37. ;************************************************************************
  38. ;************************************************************************
  39.  
  40.                         ; send errors:
  41. SERRUNREACH    equ    0            ; host or net unreachable
  42. SERRNOBUF    equ    2            ; temporary out of buffers
  43. SERRNOARP    equ    4            ; got no ARP reply
  44. SERRTIMOUT    equ    6            ; general timeout
  45. SERRNOTRAF    equ    8            ; received no traffic from dst
  46.  
  47. ICMP_PROT    equ    1            ; Internet Control Msg Prot
  48. UDP_PROT    equ    17            ; IP protocol type UDP
  49.  
  50. Descriptor    struc
  51. dLink        LinkStruc    <>        ; next & prev links
  52. ; dIOCB        iocb    <>            ; pkt drvr hi perf struc
  53. dPtrPhys    dw    0            ; ptr to physical hdr
  54. dPtrIp        dw    0            ; ptr to IP hdr
  55. dPtrUdp     dw    0            ; ptr to UDP hdr
  56. dPktLen     dw    0            ; packet length (bytes)
  57. dPktEnd     dw    0            ; end of packet
  58. dTimOut2Msg    equ    dPktEnd            ; Timeout msg for findsends
  59. dSqDelay    dw    0            ; source quench delay (ms)
  60. dWaitEvent    dw    0            ; event to wait for
  61. dPtrFrag    equ    dWaitEvent        ; ptr to defargment listhead
  62. dTimOutMsg    dw    0            ; to be displayed at timeout
  63. dTickResend    dw    1*18            ; resend start interval (ticks)
  64. dTickTimeout    dw    4*18            ; timeout ticks (in 1/18 s)
  65. dTick2Timeout    dw    14*18            ; second timeout
  66. dIdxHwDst    equ    dSqDelay        ; arp table index for hw dst
  67. dIdxIpDst    equ    dTick2Timeout        ; arp table index for IP dst
  68. dAdjust     equ    (4-(($-dLink) and 3)) and 3
  69. if    dAdjust
  70.         db    dAdjust dup (0)
  71. endif
  72. dGwys2Chk    db    0            ; # of untried gateways
  73. dSnap        db    0            ; 802.3 snaps used
  74. dPtrDes     dw    0            ; ptr to start of descriptor
  75. dHwDst        equ    $-dLink         ; (part of pd packet)
  76. DESCRLEN    equ    $-dLink
  77. Descriptor    ends
  78.  
  79. HwStruc     struc
  80. hEthDst     db    6 dup (0)        ; Ethernet destination address
  81. hEthSrc     db    6 dup (0)        ; my Ether addr
  82. hProtType    dw    0008            ; 0800 = IP
  83. HWHDRLEN    equ    $-hEthDst
  84. HwStruc     ends
  85.  
  86. SnapStruc    struc
  87. sDSAP        db    170
  88. sSSAP        db    170
  89. sContr        db    3
  90. sOrgCode    db    0,0,0
  91. sProt        db    08, 00
  92. SNAPLEN     equ    $-sDSAP
  93. SnapStruc    ends
  94.  
  95. IpStruc     struc
  96. iIpVerHlen    db    45h            ; ver 4, 5 32-bit hdr words
  97. iIpTos        db    0            ; type of service
  98. iIpLen        dw    0            ; IP packet length
  99. iIpId        dw    0100h            ; id 0001
  100. iIpFlFrag    dw    0            ; no flags or fragments
  101. iIpTtl        db    90            ; time to live
  102. iIpProt     db    0            ; 17 = udp
  103. iIpXsum     dw    0            ; header checksum
  104. iIpSrc        dw    0, 0            ; Don't know my IP nmbr
  105. iIpDst        dw    0ffffh, 0ffffh        ; local net broadcast IP
  106. iIpOptions    equ    $-iIpVerHlen
  107. IPHDRLEN    equ    $-iIpVerHlen
  108. IpStruc     ends
  109.  
  110. UdpStruc    struc
  111. uUdpSrc     dw    4400h            ; source port 44h = 68
  112. uUdpDst     dw    4300h            ; dest port 43h = 67
  113. uUdpLen     dw    0            ; length in bytes
  114. uUdpXsum    dw    0            ; udp checksum
  115. uUdpData    equ    $-uUdpSrc
  116. UDPHDRLEN    equ    $-uUdpSrc
  117. UdpStruc    ends
  118.  
  119. BootpStruc    struc
  120. uUdpStruc    UdpStruc    <>
  121. uBotOp        db    1            ; bootp request
  122. uBotHtype    db    0            ; hardware type
  123. uBotHlen    db    0            ; hardware addr lenght
  124. uBotHops    db    0            ; hops
  125. uBotXid     dw    0, 0            ; transaction id
  126. uBotSecs    dw    0001            ; 0100h seconds since boot
  127. uBotUnused    dw    0            ; not defined
  128. uBotCliIp    dw    0, 0            ; Client IP unknown
  129. uBotYourIp    dw    0, 0            ; my IP yet unknown
  130. uBotServIp    dw    0, 0            ; Server IP
  131. uBotGwyIp    dw    0, 0            ; Gateway IP
  132. uBotCliHwAd    db    16 dup (0)        ; My Hardware address
  133. uBotSname    db    64 dup (0)        ; server name
  134. uBotFilNam    db    128 dup (0)        ; file name
  135. uBotMagNum    dw    8263h, 6353h        ; Magic number
  136. uBotVend    db    64-4 dup (0)        ; Vendor specific area
  137. BpDataLen    =    $-uBotOp
  138. BootpStruc    ends
  139.  
  140. IcmpStruc    struc
  141. uIcmpTypecode    dw    0
  142. uIcmpXsum    dw    0
  143. uIcmpData    dw    0, 0
  144. uIcmpIpHdr    dw    iIpOptions+4 dup (0)
  145. ICMPHDRLEN    equ    uIcmpIpHdr-uIcmpTypecode
  146. IcmpStruc    ends
  147.  
  148. BootpFrame    struc
  149. fDescriptor    Descriptor    <>
  150. fHwStruc    HwStruc     <>
  151. fIpStruc    IpStruc     <>
  152. fBotStruc    BootpStruc    <>
  153. BpLen        =    $-fHwStruc
  154. BootpFrame    ends
  155.  
  156.         even
  157. Events        dw    1            ; =1 so DONT_WAIT always true
  158. DONT_WAIT    equ    1
  159. GOT_BOOTP    equ    2
  160. GOT_ARPREPLY    equ    4
  161. GOT_TIMEREPLY    equ    8
  162. GOT_ARPREQ    equ    16
  163. GOT_ICMPMSG    equ    32
  164. GOT_NSREPLY    equ    64
  165.  
  166. GenFlags    dw    0
  167. ARGZONE     equ    2
  168. ARGZONESPEC    equ    4
  169. DSTNOW        equ    8
  170. IS_386        equ    16
  171. TBL_READY    equ    32
  172. DBGINTERR    equ    08000h
  173.  
  174. MySegm        dw    0
  175. Hlen        dw    0
  176. H2Len        dw    0
  177. MyMask        dw    2 dup (0h)
  178. MyNet        dw    2 dup (0h)
  179. IpHandle    dw    0
  180. IpIdCounter    dw    0
  181. InSendAndW    dw    0
  182.  
  183. ifndef        MAXDEFGWYS
  184. MAXDEFGWYS    equ    4
  185. endif
  186.  
  187. DefGwyIndex    dw    0
  188. DefGwyNum    dw    0
  189. DefGwys     dw    MAXDEFGWYS*2 dup (0)
  190.  
  191. if TBLBUILD or PINGCLIENT
  192. DefNSnum    dw    0
  193. DefNS        dw    MAXDEFNS*2 dup (0)
  194. endif ; TBLBUILD or PINGCLIENT
  195.  
  196. ifndef        ROUTESLOTS
  197. ROUTESLOTS    equ    8
  198. endif
  199.  
  200. ; The route table contains information on hosts behind gateways.
  201. ;
  202. ; If we don't receive anything from an IP number within one minute after we
  203. ; last sent to it, we return SERRNOTRAF on the next send. This is cleared
  204. ; after another minute.
  205.  
  206. RouteTabIpD2    dw    ROUTESLOTS dup (0)    ; destination IP #
  207. RouteTabIpD1    dw    ROUTESLOTS dup (0)
  208. RouteTabTos    dw    ROUTESLOTS dup (0)    ; type of service
  209. RouteTabIpG2    dw    ROUTESLOTS dup (0)    ; gateway IP #
  210. RouteTabIpG1    dw    ROUTESLOTS dup (0)
  211. RouteTabTrTx    dw    ROUTESLOTS dup (0)    ; transmitt timer
  212. RouteTabTrRx    dw    ROUTESLOTS dup (0)    ; receive timer
  213. RouteTabFlags    dw    ROUTESLOTS dup (0)    ; flags (must follow TrRx)
  214. RouteTabTrSq    dw    ROUTESLOTS dup (0)    ; source quench timer
  215. RouteTabSqDelay dw    ROUTESLOTS dup (0)    ; source quench delay
  216. RouteTabUnreach dw    ROUTESLOTS dup (0)    ; destination unreachable
  217.  
  218. RoutePutSlot    dw    0
  219.  
  220. IpDesBuf    BootpFrame    <>
  221.  
  222. SnapHdr     SnapStruc    <>
  223.  
  224. IpHdr        equ    IpDesBuf.fIpStruc
  225. MyIpNr        equ    IpDesBuf.fIpStruc.iIpSrc
  226.  
  227.  
  228.  
  229. ;************************************************************************
  230. ;*        SendUdpFind
  231. ;*
  232. ;*    Input:        BX = IP description buffer ptr (BX saved)
  233. ;*            DX = addr of length prepended IP list to send to until reply
  234. ;*    Output:     Zero and CX = 0 if OK
  235. ;*            non-zero and CX = errorcode if error 
  236. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  237. ;************************************************************************
  238.  
  239. SendUdpFind    proc    near
  240.         mov    [bx].dTimoutMsg,0    ; continue even if no reply
  241.         mov    ah,2            ; do 2 turns over all IP #s
  242.   Send2ndTurn:
  243.         mov    si,dx            ; get IP list addr
  244.         lodsb                ; # of IP numbers to al
  245.         inc    si
  246.   SendNextIP:
  247.         mov    di,[bx].dPtrIp
  248.         lea    di,[di].iIpDst
  249.         movsw                ; put next IP number
  250.         movsw
  251.  
  252.         cmp    ax,0101h        ; last IP last turn?
  253.         jne    Send2orMore
  254.         mov    di,[bx].dTimOut2Msg
  255.         mov    [bx].dTimoutMsg,di    ; -yes, terminate if no reply
  256.   Send2orMore:
  257.         push    ax
  258.         push    dx
  259.         push    si
  260.         mov    ax,[bx].dPktLen
  261.         call    SendUdpPkt        ; send udp packet
  262.         pop    si
  263.         pop    dx
  264.         pop    ax
  265.         jz    SendUdpFindRet        ; done if reply
  266.  
  267.         dec    al
  268.         jnz    SendNextIP        ; more IP numbers this turn?
  269.  
  270.         mov    di,[bx].dTick2Timeout    ; -no, use longer timeout
  271.         mov    [bx].dTickTimeout,di    ;   for 2nd turn
  272.         dec    ah
  273.         jnz    Send2ndTurn        ; both turns done?
  274.  
  275.         or    cx,cx
  276.   SendUdpFindRet:
  277.         ret
  278. SendUdpFind    endp
  279.  
  280.  
  281.  
  282. ;************************************************************************
  283. ;*        SendUdpPkt
  284. ;*
  285. ;*    Input:        AX = IP data byte length (AX destroyed)
  286. ;*            BX = IP description buffer ptr (BX saved)
  287. ;*    Output:     Zero and CX = 0 if OK
  288. ;*            non-zero and CX = errorcode if error 
  289. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  290. ;************************************************************************
  291.  
  292. SendUdpPkt    proc    near
  293.         push    ax
  294.         xchg    ah,al
  295.         mov    di,[bx].dPtrUdp
  296.         mov    [di].uUdpLen,ax     ; fill in UDP total length
  297.  
  298.         mov    [di].uUdpXsum,ax    ; ensure chksum is calculated
  299.  
  300.         mov    di,[bx].dPtrIp
  301.         mov    [di].iIpProt,UDP_PROT    ; set UDP protocol
  302.  
  303.         call    UdpChkSum        ; calculate UDP checksum
  304.  
  305.         pop    ax
  306.         call    SendIpPkt        ; send UDP packet
  307.  
  308.         ret
  309. SendUdpPkt    endp
  310.  
  311.  
  312.  
  313. ;************************************************************************
  314. ;*        SendIcmpPkt
  315. ;*
  316. ;*    Input:        BX = IP description buffer ptr (BX saved)
  317. ;*            CX = IP data length
  318. ;*    Output:     Zero and CX = 0 if OK
  319. ;*            non-zero and CX = errorcode if error 
  320. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  321. ;************************************************************************
  322.  
  323. SendIcmpPkt    proc    near
  324.         push    cx            ; save length
  325.  
  326.         call    IcmpChkSum        ; calculate icmp checksum
  327.  
  328.         mov    [bx].dWaitEvent,0    ; don't wait for answer
  329.         mov    di,[bx].dPtrIp
  330.         mov    [di].iIpProt,ICMP_PROT
  331.  
  332.         pop    ax            ; restore length
  333. ;        call    SendIpPkt
  334. ;        ret
  335. SendIcmpPkt    endp
  336.  
  337.  
  338.  
  339. ;************************************************************************
  340. ;*        SendIpPkt
  341. ;*
  342. ;*    Input:        AX = IP data byte length (AX destroyed)
  343. ;*            BX = IP description buffer ptr (BX saved)
  344. ;*    Output:     Zero and CX = 0 if OK
  345. ;*            non-zero and CX = errorcode if error 
  346. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  347. ;************************************************************************
  348.  
  349. SendIpPkt    proc    near
  350.         call    IPHdrLength        ; calculate IP hdr length
  351.  
  352.         mov    dx,MyIpNr        ; my IP # to IP src
  353.         mov    [si].iIpSrc,dx
  354.         mov    dx,MyIpNr+2
  355.         mov    [si].iIpSrc+2,dx
  356.  
  357.         add    ax,cx            ; add hdr length to data length
  358.         mov    [bx].dPktLen,ax     ;   and save it
  359.  
  360.         xchg    ah,al
  361.         mov    [si].iIpLen,ax        ; fill in IP length
  362.  
  363.         mov    dx,IpIdCounter
  364.         mov    [si].iIpId,dx        ; unique id for frag reassembly
  365.         inc    dx
  366.         mov    IpIdCounter,dx
  367.  
  368.         call    IpChkSum        ; calculate checksum
  369. if RFCC
  370.         call    Ageing            ; clear unused table slots
  371. endif ; RFCC
  372.         call    PutPhysDst        ; do we have HW dest addr?
  373.         jnz    SendIpRet        ; -no, ARP timed out
  374.  
  375.         call    PutPhysSrc        ; put my HW src addr
  376.  
  377.         add    [bx].dPktLen,cx     ; pkt length (HW addr part)
  378.  
  379.         jmp    short SendAndWait    ; -yes, send packet
  380.   SendIpRet:
  381.         ret
  382. SendIpPkt    endp
  383.  
  384.  
  385.  
  386. ;************************************************************************
  387. ;*        SendAndWait
  388. ;*    Input:        BX = description buffer ptr (saved)
  389. ;*    Output:     Zero and CX = 0 if OK
  390. ;*            non-zero and CX = errorcode if error 
  391. ;*    Destroys:    AX, CX, DX, SI, DI, ES, flags
  392. ;************************************************************************
  393.  
  394. SendAndWait    proc    near
  395.         inc    InSendAndW
  396.         mov    si,[bx].dWaitEvent    ; event to wait for
  397.  
  398.         or    si,si            ; no event to wait for?
  399.         jz    SendDontWait
  400.  
  401.         not    si
  402.         and    Events,si        ; clear this event bit
  403.   SendDontWait:
  404.         not    si
  405. if RFCC
  406. ; Do RFC1016 Source Quench Introduced Delay
  407.  
  408.         mov    ax,[bx].dSqDelay    ; SQ delay (ms)
  409.         add    ax,32            ; round up
  410.         mov    cl,6
  411.         shr    ax,cl            ; convert ms to ticks
  412.         call    CurrentTicks
  413.         add    ax,cx            ; time to send at
  414.   SendSqLoop:
  415.         call    CurrentTicks
  416.         cmp    cx,ax            ; can we send it now?
  417.         jns    SendNoSqDelay
  418.         call    Something2Do        ; - no, wait a while
  419.         jmp    short SendSqLoop
  420.   SendNoSqDelay:
  421. else
  422.         call    CurrentTicks
  423. endif ; RFCC
  424.         call    SendRawPkt        ; send packet part of buffer
  425.  
  426.         mov    di,[bx].dTickResend    ; first resend time
  427.         mov    ax,cx
  428.         add    ax,di
  429.  
  430.         mov    dx,cx
  431.         add    dx,[bx].dTickTimeout    ; time out time
  432.   WaitLoop:
  433.         test    Events,si        ; got what we want?
  434.         jz    SendChk
  435.   SendWaitOK:
  436.         xor    cx,cx
  437.   SendWaitRet:
  438.         dec    InSendAndW
  439.         or    cx,cx
  440.         ret
  441.  
  442.   SendChk:
  443.         call    Something2Do        ; anything else to do?
  444.   ChkTimeout:
  445.         call    CurrentTicks
  446.         cmp    cx,dx            ; time out?
  447.         jns    SendTimedout
  448.  
  449.         cmp    cx,ax            ; time to resend?
  450.         js    WaitLoop
  451.  
  452.         shl    di,1            ; double resend time    
  453.  
  454.         cmp    di,30*18
  455.         jbe    SendDouble
  456.         mov    di,30*18        ; max 30 seconds
  457.   SendDouble:
  458.         add    ax,di            ; next resend time
  459.  
  460.         call    SendRawPkt        ; send same packet again
  461.         jmp    short WaitLoop
  462.   SendTimedout:
  463.         mov    dx,[bx].dTimOutMsg
  464.         mov    cx,SERRTIMOUT
  465.         or    dx,dx            ; if no timeout msg
  466.         jz    SendWaitRet        ;   just return
  467.  
  468.         mov    ah,9            ; print error msg in dx
  469.         int    21h
  470.         mov    al,04            ; error code 4
  471.         call    Terminate
  472. SendAndWait    endp
  473.  
  474.  
  475.  
  476. ;************************************************************************
  477. ;*        SendRawPkt
  478. ;*    Input:        BX = description buffer ptr (saved)
  479. ;*    Destroys:    flags
  480. ;*
  481. ;* (The saving of all registers below is not needed for the Crynwr
  482. ;* collection of packet drivers, but as far as I understand the packet
  483. ;* driver specification other drivers may need it.)
  484. ;************************************************************************
  485.  
  486. SendRawPkt    proc    near
  487.         push    dx
  488.         push    cx
  489.         push    bx
  490.         push    ax
  491.         push    si
  492.         push    di
  493.         push    bp
  494.         push    es
  495.  
  496.         mov    si,[bx].dPtrPhys    ; get start of packet
  497.         mov    cx,[bx].dPktLen     ; and its length
  498.  
  499.         mov    ah,4            ; send packet to
  500.         push    ds            ;   packet driver
  501.         int_pkt
  502.         pop    ds
  503.  
  504.         pop    es
  505.         pop    bp
  506.         pop    di
  507.         pop    si
  508.         pop    ax
  509.         pop    bx
  510.         pop    cx
  511.  
  512.         jc    BadPkt            ; any errors?
  513.  
  514.         pop    dx
  515.         ret
  516.   BadPkt:
  517.         call    print_error        ; display explanation
  518.  
  519.         mov    al,03            ; error code 3
  520.         call    Terminate
  521. SendRawPkt    endp
  522.  
  523.  
  524.  
  525. ;************************************************************************
  526. ;*        PutPhysSrc
  527. ;*
  528. ;*    Input:        BX = IP description buffer ptr (saved)
  529. ;*    Output:     HW src addr and IP prot type put into pkt
  530. ;*            CX = phys header length
  531. ;*    Destroys:    CX, SI, DI, ES, flags
  532. ;************************************************************************
  533.  
  534. PutPhysSrc    proc    near
  535.         mov    si,offset MyHwAd    ; get my HW addr from ARP buf
  536.         mov    di,[bx].dPtrPhys
  537.         mov    cx,Hlen
  538.         add    di,cx
  539.         push    cs
  540.         pop    es
  541.         rep    movsb            ; put my HW addr as src HW addr
  542.  
  543.         test    [bx].dSnap,1
  544.         jz    PutPhysNotSnap
  545.  
  546.         mov    cx,[bx].dPktLen
  547.         add    cx,8
  548.         xchg    ch,cl
  549.         mov    [di],cx
  550.         add    di,2
  551.  
  552.         mov    cx,sProt-sDSAP
  553.         mov    si,offset SnapHdr
  554.         rep    movsb
  555.   PutPhysNotSnap:
  556.         mov    cx,di
  557.         sub    cx,[bx].dPtrPhys
  558.         add    cx,2            ; physical header length
  559.  
  560.         mov    word ptr [di],0008h    ; protocol type IP (0800)
  561.  
  562.         ret
  563. PutPhysSrc    endp
  564.  
  565.  
  566.  
  567. ;************************************************************************
  568. ;*        PutPhysDst
  569. ;*
  570. ;*    Input:        BX = IP description buffer ptr (saved)
  571. ;*    Output:     Zero and CX = 0 if OK
  572. ;*            non-zero and CX = errorcode if error 
  573. ;*    Destroys:    AX, CX, DX, SI, DI, ES, flags
  574. ;************************************************************************
  575.  
  576. PutPhysDst    proc    near
  577.         mov    ax,DefGwyNum        ; # of default gwys we have
  578.         mov    [bx].dGwys2Chk,al    ; gwys still left to check
  579.   PutPhysAgain:
  580.         mov    di,[bx].dPtrIp
  581.         mov    al,[di].iIpTos        ; get type of service
  582.         xor    ah,ah
  583.         mov    si,ax
  584.  
  585.         mov    dx,[di].iIpDst        ; set dx,ax = dst IP #
  586.         mov    ax,[di].iIpDst+2
  587.  
  588.         call    ArpPutHwDst        ; do we know dst phys addr?
  589.         jz    FoundArpEntry        ; - yes, copied hw addr
  590.  
  591.         call    MyNetChk        ; - no. Is dst on my net?
  592.         jz    PutMynetArp        ;   - yes, don't use gwy
  593.                         ;       and ARP dst
  594.         call    UseGwy            ;   - no, use a gateway
  595.         jcxz    PutArp            ; destination unreachable?
  596.         jmp    short PutPhysRet
  597.  
  598.   PutMynetArp:
  599.         mov    [bx].dGwys2Chk,1
  600.   PutArp:
  601.         call    ArpPutHwDst        ; have hw addr for this IP # ?
  602.         jz    FoundArpEntry        ; - yes, copied hw addr to pkt
  603.  
  604.         call    SendArpReq        ; - no, arp for it
  605.         jz    PutPhysAgain        ; if reply, put in hw addr
  606.  
  607.         call    SwitchGwy        ;   else try next gwy
  608.  
  609.         mov    cx,SERRNOARP
  610.         dec    [bx].dGwys2Chk        ; any more default gwys?
  611.         jnz    PutPhysAgain
  612.  
  613.   PutPhysRet:
  614.         or    cx,cx
  615.   FoundArpEntry:
  616.         ret
  617. PutPhysDst    endp
  618.  
  619.  
  620.  
  621. ;************************************************************************
  622. ;*        RouteFind
  623. ;*
  624. ;*    Input:        DX = first word of dst IP # (saved if not found)
  625. ;*            AX = second word of dst IP # (saved if not found)
  626. ;*            SI = IP type of service
  627. ;*    Output:     if found: zero and DI = route table index
  628. ;*                  DX = first word of gwy IP #
  629. ;*                  AX = second word of gwy IP #
  630. ;*                  CX = net/host unreachable code
  631. ;*    Destroys:    CX, DI, ES, flags
  632. ;************************************************************************
  633.  
  634. RouteFind    proc    near
  635.         mov    di,offset RouteTabIpD2
  636.         mov    cx,ROUTESLOTS
  637.         or    cx,cx            ; ensure non-zero flag
  638.         PushfDI
  639.   RouteFindNext:                ; look for matching slot
  640.         repne    scasw
  641.         jnz    RouteFindRet
  642.  
  643.         cmp    dx,2*RouteSLOTS-2[di]    ; does dst IP first part match?
  644.         jne    RouteFindNext        ; - no, look further
  645.  
  646.         cmp    si,4*RouteSLOTS-2[di]    ; does dst tos    match?
  647.         jne    RouteFindNext        ; - no, look further
  648.  
  649.         sub    di,offset RouteTabIpD2+2 ;- yes, compute slot index
  650.  
  651.         mov    dx,RouteTabIpG1[di]    ; get gwy IP #
  652.         mov    ax,RouteTabIpG2[di]    ;
  653.  
  654.         mov    cx,RouteTabUnreach[di]    ; get unreachable code
  655.  
  656.         PopfEI
  657.         cmp    di,di            ; set zero flag
  658.         ret                ; zero (found) return
  659.  
  660.   RouteFindRet:
  661.         PopfEI
  662.         ret                ; non zero (not found) return
  663. RouteFind    endp
  664.  
  665.  
  666.  
  667. ;************************************************************************
  668. ;*        MyNetChk
  669. ;*
  670. ;*    Input:        DX = first word of IP # (saved)
  671. ;*            AX = second word of IP # (saved)
  672. ;*    Output:     zero if same net else non-zero 
  673. ;*    Destroys:    flags
  674. ;************************************************************************
  675.  
  676. MyNetChk    proc    near
  677.         push    ax
  678.         push    dx
  679.  
  680.         and    dx,MyMask        ; check if my net
  681.         cmp    dx,MyNet
  682.         jne    MyNetRet
  683.         and    ax,MyMask+2
  684.         cmp    ax,MyNet+2
  685.   MyNetRet:
  686.         pop    dx
  687.         pop    ax
  688.         ret
  689. MyNetChk    endp
  690.  
  691.  
  692.  
  693. ;************************************************************************
  694. ;*        UseGwy
  695. ;*
  696. ;*    Input:        DX = first word of destination IP #
  697. ;*            AX = second word of destination IP #
  698. ;*            SI = IP type of service
  699. ;*    Output:     DX = first word of gateway IP #
  700. ;*            AX = second part of gateway IP #
  701. ;*            CX = net/host unreachable code
  702. ;*    Destroys:    CX, SI, DI, ES, flags
  703. ;************************************************************************
  704.  
  705. UseGwy        proc    near
  706.         PushfDI
  707.  
  708.         call    RouteFind        ; is dst in route tbl?
  709.         jz    short UseGwyKnown    ; - yes, have gwy IP #
  710.                         ; - no, use default gwy
  711.         dec    cx
  712.         cmp    dl,127            ; don't send to 127.x.x.x
  713.         je    UseGwyRet
  714.  
  715.         mov    di,RoutePutSlot
  716.         add    di,2            ; advance index two bytes
  717.         cmp    di,ROUTESLOTS*2     ; at end of table?
  718.         jb    UseRouteSlot
  719.  
  720.         xor    di,di            ; - yes, wrap around
  721.   UseRouteSlot:
  722.         mov    RoutePutSlot,di
  723.         mov    RouteTabIpD1[di],dx    ; put destination IP #
  724.         mov    RouteTabIpD2[di],ax
  725.         mov    RouteTabTos[di],si
  726.  
  727.         mov    si,DefGwyIndex
  728.         shl    si,1
  729.         shl    si,1
  730.         mov    dx,DefGwys[si]
  731.         mov    ax,DefGwys+2[si]
  732.         mov    RouteTabIpG1[di],dx    ;   and default gwy IP #
  733.         mov    RouteTabIpG2[di],ax    ;   into route table
  734.  
  735.         call    CurrentTicks
  736.         mov    RouteTabTrRx[di],cx    ; put current time
  737.  
  738.         xor    cx,cx            ; initialize other fields
  739.         mov    RouteTabUnreach[di],cx    ;   clear unreachable
  740.         mov    RouteTabFlags[di],cx
  741.         mov    RouteTabSqDelay[di],cx
  742.  
  743.         or    si,dx
  744.         or    si,ax            ; any non-zero gwy IP #?
  745.         jz    UseGwyNone        ; - yes
  746.   UseGwyKnown:
  747. if RFCC
  748.         push    cx
  749.         push    ax
  750.         call    CurrentTicks
  751.         mov    RouteTabTrTx[di],cx    ; transmit time
  752.  
  753.         mov    ax,RouteTabSqDelay[di]    ; move sq delay to descriptor
  754.         mov    [bx].dSqDelay,ax
  755.         dec    ax            ; any delay?
  756.         js    UseNoSqDelay
  757.         mov    ax,RouteTabTrSq[di]    ; - yes
  758.         add    ax,18            ; has one second passed
  759.         cmp    ax,cx            ;   since we last decremented
  760.         jns    UseNoSqDelay        ;   the delay value?
  761.         mov    RouteTabTrSq[di],cx
  762.         dec    RouteTabSqDelay[di]    ; - yes, one millisecond off
  763.   UseNoSqDelay:
  764.         pop    ax
  765.         pop    cx
  766. endif ; RFCC
  767.   UsegwyRet:
  768.         PopfEI
  769.         ret
  770.  
  771.   UseGwyNone:
  772.         PopfEI
  773.         mov    dx,offset NoGwyMsg
  774.         mov    ah,9            ; - no, print error msg in dx
  775.         int    21h
  776.         mov    al,08            ; error code 8
  777.         call    Terminate
  778. UseGwy        endp
  779.  
  780.  
  781.  
  782. ;************************************************************************
  783. ;*        SwitchGwy
  784. ;*
  785. ;*    Input:        DX = first word of gateway IP # (saved)
  786. ;*            AX = second word of gateway IP # (saved)
  787. ;*    Destroys:    CX, DI, ES, flags
  788. ;************************************************************************
  789.  
  790. SwitchGwy    proc    near
  791.         PushfDI
  792.         mov    di,DefGwyIndex        ; if current default gateway
  793.         shl    di,1
  794.         shl    di,1
  795.  
  796.         cmp    dx,DefGwys[di]        ;   is the one
  797.         jne    SwitchNotThis
  798.         cmp    ax,DefGwys+2[di]    ;   that failed
  799.         jne    SwitchNotThis
  800.  
  801.         shr    di,1
  802.         shr    di,1
  803.         inc    di            ;   then switch to
  804.         cmp    di,DefGwyNum
  805.         jb    SwitchNextGwy
  806.         xor    di,di
  807.   SwitchNextGwy:
  808.         mov    DefGwyIndex,di        ;   next default gateway
  809.   SwitchNotThis:
  810.         PopfEI
  811.  
  812.         mov    di,offset RouteTabIpG2    ; remove failing gateway
  813.         mov    cx,ROUTESLOTS        ;   from all route slots
  814.         PushfDI
  815.   SwitchRouteNext:                ; look for matching slot
  816.         repne    scasw
  817.         jnz    SwitchGwyRet        ; all entries searched
  818.  
  819.         cmp    dx,2*ROUTESLOTS-2[di]    ; does gwy IP 2nd part match?
  820.         jne    SwitchRouteNext     ; - no, look further
  821.  
  822.         sub    di,offset RouteTabIpG2+2 ;- yes, clear this route
  823.         mov    RouteTabIpD1[di],0
  824.         mov    RouteTabIpD2[di],0
  825.         mov    RouteTabIpG1[di],0
  826.         mov    RouteTabIpG2[di],0
  827.         add    di,offset RouteTabIpG2+2
  828.         jmp    short SwitchRouteNext    ; more routes using this gwy?
  829.  
  830.   SwitchGwyRet:
  831.         PopfEI
  832.         ret
  833. SwitchGwy    endp
  834.  
  835.  
  836.  
  837. ;************************************************************************
  838. ;*        ChkSum
  839. ;*    Input:        SI = start addr
  840. ;*            CX = # of bytes
  841. ;*    Output:     AX = 1-complement checksum
  842. ;*            CX = partial checksum
  843. ;*            SI = addr of next byte
  844. ;*    Destroys:    Flags
  845. ;************************************************************************
  846.  
  847. ChkSum        proc    near
  848. if PINGCLIENT
  849.         test    GenFlags,IS_386
  850.         jz    ChkSum8086
  851.  
  852.         .386
  853.         push    edx            ; save 386 registers
  854.         push    eax
  855.         shr    cx,1            ; divide by two, round down
  856.         pushf                ; keep odd bit in carry
  857.         shr    cx,1
  858.         pushf
  859.         xor    edx,edx            ; clear edx and carry
  860.   ChkLoop386:
  861.         lodsd
  862.         adc    edx,eax            ; add to previous running sum
  863.         loopw    ChkLoop386
  864.  
  865.         adc    edx,0            ; add the last carry in again
  866.         mov    eax,edx
  867.         shr    eax,16
  868.         add    dx,ax
  869.         adc    dx,0
  870.  
  871.         popf                ; odd # of words?
  872.         jnc    NotOddWords
  873.  
  874.         lodsw
  875.         add    dx,ax
  876.         adc    dx,0
  877.   NotOddWords:
  878.         popf                ; odd # of bytes?
  879.         jnc    NotOddBytes
  880.  
  881.         lodsb                ; get that last byte
  882.         xor    ah,ah            ; clear carry and the high portion
  883.         add    dx,ax            ; add the last one in
  884.         adc    dx,0            ; add the carry in, too
  885.   NotOddBytes:
  886.         pop    eax
  887.         mov    ax,dx
  888.         mov    cx,dx
  889.         pop    edx
  890.  
  891.         not    ax            ; take one more 1-complement
  892.         ret
  893.  
  894.         .8086
  895. endif ; PINGCLIENT
  896.  
  897.   ChkSum8086:
  898.         push    dx
  899.         shr    cx,1            ; divide by two, round down
  900.         pushf                ; keep odd bit in carry
  901.         xor    dx,dx            ; clear dx and carry
  902.   ChkLoop:
  903.         lodsw
  904.         adc    dx,ax            ; add to previous running sum
  905.         loop    ChkLoop
  906.  
  907.         adc    dx,0            ; add the last carry in again
  908.  
  909.         popf                ; odd # of bytes?
  910.         jnc    NotOdd
  911.  
  912.         lodsb                ; get that last byte
  913.         xor    ah,ah            ; clear carry and the high portion
  914.         add    dx,ax            ; add the last one in
  915.         adc    dx,0            ; add the carry in, too
  916.   NotOdd:
  917.         mov    ax,dx
  918.         mov    cx,dx
  919.         pop    dx
  920.  
  921.         not    ax            ; take one more 1-complement
  922.         ret
  923. ChkSum        endp
  924.  
  925.  
  926.  
  927. ;************************************************************************
  928. ;*        UdpChkSum (both for generate and check!)
  929. ;*
  930. ;*    Input:        BX = IP description buffer ptr (saved)
  931. ;*    Output:     Zero if OK; checksum filled in
  932. ;*            SI = addr of next byte
  933. ;*            DI = IP Ptr
  934. ;*    Destroys:    AX, CX, DX, SI, DI, flags
  935. ;************************************************************************
  936.  
  937. UdpChkSum    proc    near
  938.         mov    si,[bx].dPtrIp
  939.         mov    di,[bx].dPtrUdp
  940.  
  941.         xor    cx,cx            ; save ttl for pseudo hdr
  942.         xchg    cl,[si].iIpTtl        ;   usage
  943.         push    cx
  944.  
  945.         xor    dx,dx
  946.         xchg    dx,[di].uUdpXsum    ; save and clear checksum
  947.  
  948.         mov    cx,[di].uUdpLen     ; save UDP length
  949.         mov    [si].iIpXsum,cx
  950.         xchg    ch,cl
  951.  
  952.         mov    ax,di
  953.         add    ax,cx
  954.         or    dx,dx            ; is there a checksum?
  955.         mov    si,ax            ; - no, not available/wanted
  956.         jz    UdpNoSum        ;   but set si to end of data
  957.  
  958.         push    cx            ; - yes
  959.         mov    cx,12            ; checksum pseudo hdr
  960.         mov    si,[bx].dPtrIp
  961.         add    si,iIpTtl
  962.         call    ChkSum
  963.  
  964.         mov    [di].uUdpXsum,cx    ; move partial checksum
  965.                         ;   into udp hdr
  966.         pop    cx            ; checksum udp hdr+data
  967.         mov    si,di
  968.         call    ChkSum
  969.         jnz    UdpNotZero        ; checksum is zero?
  970.         not    ax            ; - yes, make it FFFFh
  971.   UdpNotZero:
  972.         mov    [di].uUdpXsum,ax
  973.  
  974.         cmp    ax,dx            ; does checksums match?
  975.   UdpNoSum:
  976.         pop    cx
  977.         mov    di,[bx].dPtrIp
  978.         mov    [di].iIpTtl,cl        ; restore ttl
  979.  
  980.         ret
  981. UdpChkSum    endp
  982.  
  983.  
  984.  
  985. ;************************************************************************
  986. ;*        IpHdrLength
  987. ;*
  988. ;*    Input:        BX = IP description buffer ptr (saved)
  989. ;*    Output:     CX = IP header byte length
  990. ;*            SI = pointer to IP header
  991. ;*    Destroys:    SI, flags
  992. ;************************************************************************
  993.  
  994. IpHdrLength    proc    near
  995.         mov    si,[bx].dPtrIp
  996.         mov    cx,[si]         ; get version+length byte
  997.         and    cx,0fh            ; length (32 bit words)
  998.         shl    cx,1            ; convert to
  999.         shl    cx,1            ;   byte length
  1000.         ret
  1001. IpHdrLength    endp
  1002.  
  1003.  
  1004.  
  1005. ;************************************************************************
  1006. ;*        IpChkSum (both for generate and check!)
  1007. ;*
  1008. ;*    Input:        BX = IP description buffer ptr (saved)
  1009. ;*    Output:     Zero if OK; checksum filled in
  1010. ;*    Destroys:    AX, CX, DX, SI, DI, flags
  1011. ;************************************************************************
  1012.  
  1013. IpChkSum    proc    near
  1014.         xor    dx,dx
  1015.         mov    di,[bx].dPtrIp
  1016.         xchg    dx,[di].iIpXsum     ; save and clear checksum
  1017.  
  1018.         call    IpHdrLength
  1019.         call    ChkSum            ; calculate new checksum
  1020.         mov    [di].iIpXsum,ax
  1021.  
  1022.         cmp    ax,dx            ; does checksums match?
  1023.         ret
  1024. IpChkSum    endp
  1025.  
  1026.  
  1027.  
  1028. ;************************************************************************
  1029. ;*        IcmpChkSum (both for generate and check!)
  1030. ;*
  1031. ;*    Input:        BX = IP description buffer ptr (saved)
  1032. ;*            CX = IP data length
  1033. ;*    Output:     Zero if OK; checksum filled in
  1034. ;*    Destroys:    AX, CX, DX, SI, DI, flags
  1035. ;************************************************************************
  1036.  
  1037. IcmpChkSum    proc    near
  1038.         xor    dx,dx
  1039.         mov    di,[bx].dPtrUdp
  1040.         xchg    dx,[di].uIcmpXsum    ; save and clear checksum
  1041.  
  1042.         mov    si,di
  1043.         call    ChkSum            ; calculate new checksum
  1044.         mov    [di].uIcmpXsum,ax
  1045.  
  1046.         cmp    ax,dx            ; does checksums match?
  1047.         ret
  1048. IcmpChkSum    endp
  1049.  
  1050.  
  1051.  
  1052. ;************************************************************************
  1053. ;*        CurrentTicks
  1054. ;*    Output:     CX = low word of ticks (1/18 second) counter
  1055. ;*    Destroys:    CX, ES
  1056. ;************************************************************************
  1057.  
  1058. CurrentTicks    proc    near
  1059.         mov    cx,040h         ; DOS data segment
  1060.         mov    es,cx
  1061.         mov    cx,es:6ch        ; get low word of ticks cntr
  1062.         push    cs
  1063.         pop    es
  1064.         ret
  1065. CurrentTicks    endp
  1066.  
  1067.  
  1068. if RFCC
  1069. ;************************************************************************
  1070. ;*        Ageing of ARP and Route tables
  1071. ;*
  1072. ;*    Destroys:    AX, CX, DX, SI, DI, ES, flags
  1073. ;************************************************************************
  1074.  
  1075. AgeNext     dw    0            ; time to check slots
  1076.  
  1077. Ageing        proc    near
  1078.         PushfDI
  1079.         call    CurrentTicks        ; get current ticks value
  1080.         cmp    cx,AgeNext
  1081.         jns    AgeNow            ; time to do ageing?
  1082.  
  1083.         PopfEI
  1084.         ret
  1085.  
  1086.   AgeNow:
  1087.         mov    di,cx
  1088.         mov    dx,cx
  1089.         add    cx,2*18         ; chk next 2 seconds from now
  1090.         mov    AgeNext,cx
  1091.  
  1092.         sub    dx,65*18        ; clear what is older than 1 min
  1093.  
  1094.         mov    cx,ARPSLOTS-3
  1095.         mov    si,offset ArpTabTr+6
  1096.   AgeArpLoop:
  1097.         and    word ptr [si+2*ARPSLOTS],not SQ_UPDATED ; clr every 2 s
  1098.  
  1099.         lodsw
  1100.         cmp    ax,dx
  1101.         jns    AgeArpYoung        ; not touched in a minute?
  1102.  
  1103.         sub    si,offset ArpTabTr+2
  1104.         push    cx
  1105.         push    di
  1106.         push    dx
  1107.         mov    dx,ArpTabIp1[si]
  1108.         mov    ax,ArpTabIp2[si]
  1109.         call    switchGwy        ; in case it's a gwy: switch
  1110.         pop    dx
  1111.         pop    di
  1112.         pop    cx
  1113.  
  1114.         xor    ax,ax
  1115.         mov    ArpTabTr[si],di     ; set current time
  1116.         mov    ArpTabIp1[si],ax    ; clear old entries
  1117.         mov    ArpTabIp2[si],ax
  1118.         mov    ArpTabHw1[si],ax
  1119.         mov    ArpTabHw2[si],ax
  1120.         mov    ArpTabHw3[si],ax
  1121.         add    si,offset ArpTabTr+2
  1122.   AgeArpYoung:
  1123.         loop    AgeArpLoop
  1124.         PopfEI
  1125.  
  1126.         mov    cx,ROUTESLOTS
  1127.         mov    si,offset RouteTabTrRx
  1128.         PushfDI
  1129.   AgeRouteLoop:
  1130.         and    word ptr [si+2*ROUTESLOTS],not SQ_UPDATED ; clr every 2 s
  1131.  
  1132.         lodsw
  1133.         cmp    ax,dx            ; old slot?
  1134.         jns    AgeRouteYoung
  1135.  
  1136.         sub    si,offset RouteTabTrRx+2
  1137.         mov    RouteTabTrRx[si],di
  1138.         xor    ax,ax
  1139.         cmp    RouteTabUnreach[si],ax    ; any error code?
  1140.         jne    AgeRouteUnr
  1141.  
  1142.         cmp    dx,RouteTabTrTx[si]    ; - no. Sent anything lately?
  1143.         jns    AgeRouteEnd        ;    - no, that's why
  1144.  
  1145.         mov    RouteTabUnreach[si],SERRNOTRAF ;- yes, somebody is dead
  1146.         jmp    short AgeRouteEnd
  1147.   AgeRouteUnr:                    ; - yes, remove slot
  1148.         mov    RouteTabIpD1[si],ax
  1149.         mov    RouteTabIpD2[si],ax
  1150.         mov    RouteTabIpG1[si],ax
  1151.         mov    RouteTabIpG2[si],ax
  1152.   AgeRouteEnd:
  1153.         add    si,offset RouteTabTrRx+2
  1154.   AgeRouteYoung:
  1155.         loop    AgeRouteLoop
  1156.  
  1157.         PopfEI
  1158.         call    AgeFrags        ; release old fragments
  1159.  
  1160.         ret
  1161. Ageing        endp
  1162.  
  1163.  
  1164.  
  1165. ;************************************************************************
  1166. ;*        VerifyIpHdr (RFC1122 requirements)
  1167. ;*
  1168. ;* verify IP dst = me (or bcast), process IP options, verify IPver=4,
  1169. ;* verify IP src not bcast, set timer value in ArpTab and RouteTab.
  1170. ;* Process IP fragments.
  1171. ;************************************************************************
  1172.  
  1173. holeStruc    struc
  1174. holeNext    dw    0
  1175. holeFirst    dw    0
  1176. holeLast    dw    0
  1177. HOLEDESCRLEN    equ    $-holeNext
  1178. holeStruc    ends
  1179.  
  1180. k18        db    18
  1181.  
  1182. VerifyIpHdr    proc    near
  1183.         push    si
  1184.         push    di
  1185.         mov    al,[di].iIpVerHlen
  1186.         and    al,0f0h
  1187.         cmp    al,040h         ; IP version 4?
  1188.         jne    VerifyErr1
  1189.  
  1190.         mov    di,[bx].dPtrPhys
  1191.         mov    si,[di]
  1192.         mov    dx,[di+2]
  1193.         mov    ax,[di+4]
  1194.         call    ArpFindHw        ; find Hw Dst arp index
  1195.         mov    [bx].dIdxHwDst,di    ;   0 = bcast, 4 = me
  1196.  
  1197.         cmp    MyIpNr,0
  1198.         je    VerifyMeNotInArp
  1199.  
  1200.         cmp    di,ARPMYIDX        ; is Hw addr to me or bcats?
  1201.         ja    VerifyErr1
  1202.   VerifyMeNotInArp:
  1203.         mov    di,[bx].dPtrPhys
  1204.         add    di,Hlen         ; get physical src addr
  1205.         mov    si,[di]
  1206.         mov    dx,[di+2]
  1207.         mov    ax,[di+4]
  1208.         call    ArpFindHw        ; is Hw Src in arp table?
  1209.         jz    VerifyChkBcast        ; - yes
  1210.  
  1211.         cmp    [bx].dIdxHwDst,ARPMYIDX ; - no. Addressed to me?
  1212.         jne    VerifyIpDst        ; 
  1213.  
  1214.         pop    di            ; - yes
  1215.         push    di
  1216.         mov    dx,[di].iIpSrc
  1217.         mov    ax,[di].iIpSrc+2
  1218.  
  1219.         call    MyNetChk        ; if he is on my net
  1220.         jnz    VerifyIpDst
  1221.  
  1222.         mov    si,[bx].dPtrPhys
  1223.         add    si,Hlen
  1224.         call    ArpPutNew        ;   add him to arp table
  1225.         jmp    short VerifyIpDst
  1226.  
  1227.   VerifyErr1:    jmp    short VerifyErr
  1228.  
  1229.   VerifyChkBcast:
  1230.         cmp    di,ARPMYIDX        ; from me or broadcast?
  1231.         jbe    VerifyErr        ; - yes, ignore packet
  1232.  
  1233.         call    CurrentTicks        ; get current ticks value
  1234.         mov    ArpTabTr[di],cx
  1235.   VerifyIpDst:
  1236.         cmp    MyIpNr,0
  1237.         je    VerifyIpUnknown
  1238.  
  1239.         pop    di
  1240.         push    di
  1241.         mov    dx,[di].iIpDst        ; check IP dst
  1242.         mov    ax,[di].iIpDst+2
  1243.         call    ArpFindIp
  1244.         mov    [bx].dIdxIpDst,di
  1245.         cmp    di,ARPMYIDX        ; is it to me or broadcast?
  1246.         ja    VerifyErr        ; - no, ignore packet
  1247.   VerifyIpUnknown:
  1248.         pop    di
  1249.         push    di
  1250.         mov    dx,[di].iIpSrc
  1251.         mov    ax,[di].iIpSrc+2
  1252.         call    ArpFindIp
  1253.         jnz    VerifyNoArp
  1254.  
  1255.         cmp    di,ARPMYIDX        ; from IP broadcast?
  1256.         jb    VerifyErr        ; -yes, ignore packet
  1257.   VerifyOK:
  1258.         call    AgeFrags        ; release old reassembly bufs
  1259.  
  1260.         pop    di
  1261.         push    di
  1262.         test    [di].iIpFlFrag,0ff3fh    ; is this a fragment?
  1263.         jnz    VerifyFrag
  1264.         clc                 ; - no, use as is
  1265.   VerifyRet:
  1266.         pop    di
  1267.         pop    si
  1268.         ret
  1269.  
  1270.   VerifyNoArp:
  1271.         pop    di
  1272.         push    di
  1273.         mov    cl,[di].iIpTos
  1274.         xor    ch,ch
  1275.         mov    si,cx
  1276.         call    RouteFind        ; is he in route table?
  1277.         jnz    VerifyNoRoute
  1278.  
  1279.         call    CurrentTicks
  1280.         mov    RouteTabTrRx[di],cx    ; note we've got pkts from him
  1281.   VerifyNoRoute:
  1282.         jmp    short VerifyOK
  1283.  
  1284.   FragAddAndErr:
  1285.         mov    si,offset FragList
  1286.         call    AddToList
  1287.   VerifyFragErr:
  1288.         mov    bx,bp
  1289.   VerifyErr:
  1290.         call    BufRelease
  1291.   VerifyKeep:
  1292.         stc
  1293.         jmp    short VerifyRet
  1294.  
  1295.   VerifyFrag:        ; RFC 815 fragment reassembly:
  1296.         mov    bp,bx            ; addr of fragment buffer
  1297.         mov    dx,[di].iIpSrc        ; get IP # / IP id / IP prot
  1298.         mov    ax,[di].iIpSrc+2
  1299.         mov    si,[di].iIpId
  1300.         mov    cx,Fraglist.lBufsAvail
  1301.         mov    ch,[di].iIpProt
  1302.   FragLook4Buf:
  1303.         mov    di,offset FragList
  1304.         call    GetFromList
  1305.         jz    FragEarliest        ; any reassembly buffers?
  1306.  
  1307.         mov    di,[bx].dPtrIp        ; match IP#/Id/Prot
  1308.         cmp    dx,[di].iIpSrc
  1309.         jne    FragNextBuf
  1310.         cmp    ax,[di].iIpSrc+2
  1311.         jne    FragNextBuf
  1312.         cmp    si,[di].iIpId
  1313.         jne    FragNextBuf
  1314.         cmp    ch,[di].iIpProt
  1315.         je    FragBufFound
  1316.   FragNextBuf:
  1317.         push    si            ; irrelevant buf, put it back
  1318.         mov    si,offset FragList
  1319.         call    AddToList
  1320.         pop    si
  1321.         dec    cl
  1322.         jnz    FragLook4Buf
  1323.   FragEarliest:
  1324.         call    FragFirstLast        ; compute addr of fragment
  1325.         or    ax,ax            ; first part earliest?
  1326.         jnz    FragOffset
  1327.  
  1328.         mov    bx,bp        
  1329.         mov    di,[bx].dPtrUdp
  1330.         add    di,dx
  1331.         cmp    [bp].dHomeList,offset FreeBufs ;   and a big buffer?
  1332.         je    FragFirstHole        ; - yes, no extra buffer needed
  1333.   FragOffset:
  1334.         call    BufAlloc        ; - no, create empty buffer
  1335.         jz    VerifyFragErr
  1336.  
  1337.         add    di,2+2*EADDR_LEN
  1338.         mov    [bx].dPtrIp,di
  1339.  
  1340.         mov    si,[bp].dPtrIP
  1341.         mov    cx,[bp].dPtrUdp        ; copy IP header
  1342.         sub    cx,si
  1343.         call    movemem
  1344.         mov    [bx].dPtrUdp,di
  1345.   FragFirstHole:
  1346.         mov    [di].holeNext,0     ; create first hole descriptor
  1347.         mov    [di].holeFirst,0
  1348.         mov    [di].holeLast,GIANT
  1349.         mov    [bx].dPtrFrag,di
  1350.  
  1351.         add    di,HOLEDESCRLEN     ; mark end of info
  1352.         mov    [bx].dPktEnd,di
  1353.   FragBufFound:
  1354.         call    FragFirstLast        ; compute addr of fragment
  1355.         lea    di,[bx].dPtrFrag
  1356.   FragNextHole:                 ; 1. select next hole descr
  1357.         mov    si,di
  1358.         mov    di,[si].holeNext
  1359.         or    di,di            ;    any more descriptors?
  1360.         jz    FragEndHoles
  1361.  
  1362.         cmp    ax,[di].holeLast    ; 2. frag.first > hole.last?
  1363.         jae    FragNextHole
  1364.  
  1365.         cmp    dx,[di].holeFirst    ; 3. frag.last < hole.first?
  1366.         jbe    FragNextHole
  1367.  
  1368.         mov    cx,[di].holeNext    ; 4. delete current hole descr
  1369.         mov    [si].holeNext,cx
  1370.  
  1371.         mov    cx,[di].holeLast
  1372.         cmp    ax,[di].holeFirst    ; 5. frag.first > hole.first?
  1373.         jbe    FragNoNew1
  1374.         mov    [si].holeNext,di    ;    create new hole descr
  1375.         mov    [di].holeLast,ax
  1376.   FragNoNew1:
  1377.         mov    si,[bp].dPtrIp        ; 6. if frag.more
  1378.         test    [si].iIpFlFrag,0020h
  1379.         jz    FragLastFrag
  1380.  
  1381.         cmp    dx,cx            ;    and frag.last < hole.last?
  1382.         jae    FragNextHole
  1383.  
  1384.         mov    si,[bx].dPtrUdp
  1385.         add    si,dx
  1386.         mov    [si].holeFirst,dx    ;    create new hole descr
  1387.         mov    [si].holeLast,cx
  1388.         mov    cx,[bx].dPtrFrag
  1389.         mov    [si].holeNext,cx
  1390.         mov    [bx].dPtrFrag,si
  1391.  
  1392.         add    si,HOLEDESCRLEN
  1393.         cmp    si,[bx].dPktEnd
  1394.         jbe    FragNextHole
  1395.   FragPktEnd:
  1396.         mov    [bx].dPktEnd,si
  1397.         jmp    short FragNextHole
  1398.  
  1399.   FragLastFrag:                 ; when last frag
  1400.         mov    si,[bx].dPtrUdp     ;   prepare IP length
  1401.         add    si,dx
  1402.         jmp    short FragPktEnd
  1403.  
  1404.   FragEndHoles:                 ; 8. copy data to assembly buf
  1405.         cmp    bx,bp            ; do we need to copy?
  1406.         je    FragTimeUpd
  1407.  
  1408.         or    ax,ax            ; if first frag
  1409.         jnz    FragNotFirst
  1410.  
  1411.         mov    si,[bx].dPtrUdp     ;   retain this IP header
  1412.         mov    di,[bp].dPtrUdp     ;   and copy assembled data
  1413.         mov    cx,[bx].dPktEnd     ;   to frag buffer
  1414.         sub    cx,si
  1415.         add    si,dx            ;   skip over first fragment
  1416.         add    di,dx
  1417.         sub    cx,dx
  1418.         call    movemem
  1419.         mov    [bp].dPktEnd,di
  1420.  
  1421.         mov    cx,[bx].dPtrFrag
  1422.         mov    [bp].dPtrFrag,cx
  1423.  
  1424.         xchg    bx,bp            ;   and switch buffers
  1425.  
  1426.         mov    cx,di
  1427.         sub    cx,si            ;   hole ptr adjustment
  1428.         lea    di,[bx].dPtrFrag
  1429.   FragUpdLoop:
  1430.         mov    si,di
  1431.         mov    di,[si].holeNext
  1432.         or    di,di
  1433.         jz    FragRelBuf        ;   end of hole list 
  1434.  
  1435.         add    di,cx
  1436.         mov    [si].holeNext,di    ;   new pointer address
  1437.         jmp    short FragUpdLoop
  1438.  
  1439.   FragNotFirst:
  1440.         mov    si,[bp].dPtrUdp     ; copy this frag to asm buf
  1441.         mov    cx,dx
  1442.         sub    cx,ax
  1443.         mov    di,[bx].dPtrUdp
  1444.         add    di,ax
  1445.         call    movemem
  1446.   FragRelBuf:
  1447.         push    bx            ; release frag buf
  1448.         mov    bx,bp
  1449.         call    BufRelease
  1450.         pop    bx
  1451.   FragTimeUpd:
  1452.         call    CurrentTicks        ; update timer entry
  1453.         mov    di,[bx].dPtrIp
  1454.         mov    al,[di].iIpTtl
  1455.         mul    k18
  1456.         add    cx,ax
  1457.         mov    [bx].dTickTimeout,cx
  1458.  
  1459.         mov    di,[bx].dPtrIp
  1460.         mov    si,[bx].dPtrUdp
  1461.         cmp    [bx].dPtrFrag,0     ; any holes?
  1462.         jne    FragKeep        ; - yes, wait for more pkts
  1463.  
  1464.         mov    cx,[bx].dPktEnd     ; - no
  1465.         mov    ax,cx            ; compute IP length
  1466.         sub    cx,[bx].dPtrIp
  1467.         xchg    ch,cl
  1468.         mov    [di].iIpLen,cx
  1469.         sub    ax,[bx].dPtrPhys
  1470.         mov    [bx].dPktLen,ax     ;   and packet length
  1471.  
  1472.         add    sp,4            ; pop si and pop di
  1473.         ret
  1474.  
  1475.   FragKeep:
  1476.         mov    si,offset FragList    ; keep buf a while
  1477.         call    AddToList
  1478.         jmp    VerifyKeep
  1479. VerifyIpHdr    endp
  1480.  
  1481.  
  1482.  
  1483. ;************************************************************************
  1484. ;*        FragFirstLast
  1485. ;************************************************************************
  1486.  
  1487. FragFirstLast    proc    near
  1488.         mov    di,[bp].dPtrIp        ; compute frag.first
  1489.         mov    ax,[di].iIpFlFrag
  1490.         xchg    ah,al
  1491.         and    ax,1fffh
  1492.         shl    ax,1
  1493.         shl    ax,1
  1494.         shl    ax,1
  1495.         mov    dx,[di].iIpLen        ; compute frag.last (+1)
  1496.         xchg    dh,dl
  1497.         add    dx,[bp].dPtrIp
  1498.         sub    dx,[bp].dPtrUdp
  1499.         add    dx,ax
  1500.         cmp    dx,GIANT-IPHDRLEN-HWHDRLEN ; fits in buffer?
  1501.         ja    FragTooBig
  1502.  
  1503.         ret
  1504.  
  1505.   FragTooBig:
  1506.         add    sp,2            ; remove return addr from stack
  1507.         jmp    FragAddAndErr
  1508. FragFirstLast    endp
  1509.  
  1510.  
  1511.  
  1512. ;************************************************************************
  1513. ;*        AgeFrags
  1514. ;************************************************************************
  1515.  
  1516. AgeFragsNext    dw    0
  1517.  
  1518. AgeFrags    proc    near
  1519.         call    CurrentTicks
  1520.         cmp    cx,AgeFragsNext
  1521.         jns    AgeFragsNow        ; time to age yet?
  1522.  
  1523.         ret
  1524.  
  1525.   AgeFragsNow:
  1526.         mov    dx,cx
  1527.         add    cx,2*18         ; check next in 2 seconds
  1528.         mov    AgeFragsNext,cx
  1529.  
  1530.         push    bx
  1531.         PushfDI
  1532.         mov    cx,Fraglist.lBufsAvail
  1533.   AgeLook4Buf:
  1534.         mov    di,offset FragList
  1535.         call    GetFromList
  1536.         jz    AgeNoMoreFrags        ; any reassembly buffers?
  1537.  
  1538.         mov    si,offset FragList
  1539.         cmp    dx,[bx].dTickTimeout
  1540.         js    AgenextBuf        ; too old?
  1541.                         ; - no, put it back
  1542.         mov    si,[bx].dHomeList    ; - yes, release it
  1543.   AgeNextBuf:
  1544.         call    AddToList            
  1545.  
  1546.         dec    cl
  1547.         jnz    AgeLook4Buf        ; any more reassembly bufs?
  1548.   AgeNoMoreFrags:
  1549.         PopfEI
  1550.         pop    bx
  1551.         ret
  1552. AgeFrags    endp
  1553.  
  1554. endif ; RFCC
  1555.  
  1556. ;************************************************************************
  1557. ;*        SwitchIpDst
  1558. ;************************************************************************
  1559.  
  1560. SwitchIpDst    proc    near
  1561.         mov    si,[bx].dPtrIp
  1562. SwitchIpDstB:
  1563.         mov    dx,[si].iIpSrc        ; mov his IP # to IP dst
  1564.         mov    di,[bx].dPtrIp
  1565.         mov    [di].iIpDst,dx
  1566.         mov    dx,[si].iIpSrc+2
  1567.         mov    [di].iIpDst+2,dx
  1568.         ret
  1569. SwitchIpDst    endp
  1570.  
  1571.  
  1572.  
  1573. ;************************************************************************
  1574. ;*        InitIp
  1575. ;************************************************************************
  1576.  
  1577. InitIp        proc    near
  1578.         pushf
  1579.         pop    ax
  1580.         or    ax,7000h        ;the 386 lets us set these bits
  1581.         push    ax
  1582.         popf
  1583.         pushf
  1584.         pop    ax
  1585.         test    ax,7000h        ;did the bits get set?
  1586.         jz    IsNot386        ;no.
  1587.         or    GenFlags,IS_386        ;yes, use a 386-optimized code
  1588.   IsNot386:
  1589.         push    ds
  1590.         mov    IpDesBuf.dPtrPhys,offset IpDesBuf.fHwStruc ; *test*
  1591.         mov    IpDesBuf.dPtrIp,offset IpDesBuf.fIpStruc
  1592.         mov    IpDesBuf.dPtrUdp,offset IpDesBuf.fBotStruc
  1593.  
  1594.         mov    ax,1ffh         ;driver_info
  1595.         int_pkt
  1596.         pop    ds
  1597.         call    fatal_error
  1598.  
  1599.         mov    ah,2            ;access all packets.
  1600.         mov    al,ch            ;their class from driver_info().
  1601.         mov    bx,dx            ;their type from driver_info().
  1602.         mov    dl,cl            ;their number from driver_info().
  1603.         mov    cx,2            ;type length of two.
  1604.         mov    si,offset IpDesBuf.fHwStruc.hProtType
  1605.         push    cs            ;es:di -> our receiver.
  1606.         pop    es
  1607.         mov    di,offset IpRecv
  1608.  
  1609.         push    ds
  1610.         int_pkt
  1611.         pop    ds
  1612.  
  1613.         call    fatal_error
  1614.  
  1615.         mov    IpHandle,ax
  1616.  
  1617.         ret
  1618. InitIp        endp
  1619.  
  1620.  
  1621.  
  1622. ;************************************************************************
  1623. ;*        EndProtocol
  1624. ;************************************************************************
  1625.  
  1626. EndProtocol    proc    near
  1627.         mov    ah,3            ; release handle in bx
  1628.  
  1629.         push    ds
  1630.         int_pkt
  1631.         pop    ds
  1632.  
  1633.         call    print_error
  1634.  
  1635.         ret
  1636. EndProtocol    endp
  1637.  
  1638.  
  1639.  
  1640. ;************************************************************************
  1641. ;*        Terminate
  1642. ;************************************************************************
  1643.  
  1644. Terminate    proc    near
  1645.         pop    bx            ; remove return addr fr stack
  1646.         push    ax
  1647.  
  1648.         cld
  1649.         push    cs
  1650.         push    cs
  1651.         pop    ds
  1652.         pop    es
  1653.         sti
  1654.  
  1655.         mov    bx,IpHandle        ; release ARP and IP handles
  1656.         call    EndProtocol
  1657.         mov    bx,ArpHandle
  1658.         call    EndProtocol
  1659. if PINGCLIENT
  1660.         cmp    EchoTarget,0
  1661.         jz    TermNoPing
  1662.         call    RestoreTimer
  1663.   TermNoPing:
  1664. endif ; PINGCLIENT
  1665.         pop    ax
  1666.         push    ax
  1667.         or    al,al            ; any errors?
  1668.         jz    termnorm
  1669.  
  1670.         cmp    EnoughWord,HAVE_MYIPNR    ; clock errors?
  1671.         je    termnorm
  1672.  
  1673.         mov    dx,offset MsgNotSet    ; display "clock not set"
  1674.         mov    ah,9
  1675.         int    21h
  1676.   termnorm:
  1677.         pop    ax
  1678.         push    ax
  1679.         add    al,'0'
  1680.         mov    MsgTermNr,al        ; show error # in end line
  1681.  
  1682.         mov    si,offset MyHwAd
  1683.         mov    di,offset MsgTermHw
  1684.         call    PutHwNum        ; put my HW addr
  1685.  
  1686.         mov    si,offset MyIpNr
  1687.         mov    di,offset MsgMyIp
  1688.         call    PutIpNum        ; put my IP #
  1689.  
  1690.         mov    dx,offset MsgTerm    ; End of PDCLKSET msg
  1691.         mov    ah,9
  1692.         int    21h
  1693.  
  1694.         pop    ax            ; error code
  1695.         mov    ah,4ch
  1696.         int    21h            ; terminate program
  1697. Terminate    endp
  1698.  
  1699.  
  1700.  
  1701.  
  1702. ;************************************************************************
  1703. ;*        IP receiver                        *
  1704. ;************************************************************************
  1705.  
  1706. IpRecv:
  1707.         pushf
  1708.         push    ds            ; set segment registers
  1709.         mov    dx,cs
  1710.         mov    ds,dx
  1711.         mov    es,dx
  1712.         cld
  1713.  
  1714.         or    ax,ax            ; first or second call?
  1715.         jne    IpRecv_1        ; - second, we've got data
  1716.                         ; - first, they want a buf
  1717.         cmp    cx,GIANT        ; packet too long?
  1718.         ja    IpRecTooBig
  1719. if PINGCLIENT
  1720.         cmp    cx,BUFBODYSML
  1721.         ja    IpRecBig
  1722.  
  1723.         call    BufAlSml
  1724.         jz    IpRecBig
  1725.         pop    ds
  1726.         popf
  1727.         retf
  1728.  
  1729.   IpRecBig:
  1730. endif ; PINGCLIENT
  1731.         call    BufAlloc        ; get a receive buffer
  1732.         jz    IpRecNoBuf
  1733.   IpRecRet0:
  1734.         pop    ds
  1735.         popf
  1736.         retf
  1737.  
  1738. if DEBUG
  1739.   DbgIpRecv:
  1740.         or    GenFlags,DBGINTERR
  1741. endif ; DEBUG
  1742.   IpRecNoBuf:
  1743. if PINGCLIENT
  1744.         inc    EchoDrop
  1745. endif ; PINGCLIENT
  1746.   IpRecTooBig:
  1747.         xor    di,di            ; no buffer available
  1748.         mov    es,di
  1749.         jmp    short IpRecRet0
  1750.  
  1751.  
  1752.   IpRecv_1:
  1753.  
  1754. ; If I understand PC interrupt handling correctly, the following stackswitch
  1755. ; and interrupt enabling should not kill multiprocess reentrancy.
  1756.  
  1757.         cli                ; switch to our
  1758.         mov    word ptr SaveSP,sp    ;   interrupt stack
  1759.         mov    word ptr SaveSS,ss
  1760.         mov    sp,offset StackEnd
  1761.         mov    ss,MySegm
  1762.         sti                ; allow interrupts
  1763. if DEBUG
  1764.         dec    DbgIntCnt        ; double interrupt?
  1765.         jnz    DbgIpRecv
  1766. endif ; DEBUG
  1767.         call    BuildRecDescr        ; calculate pointers etc
  1768.  
  1769.         call    IpChkSum        ; only accept a correct
  1770.         jne    IpRecRet        ;   IP checksum
  1771.  
  1772.         mov    [bx].dPtrUdp,si
  1773. if RFCC
  1774.         call    VerifyIpHdr        ; verify and process IP hdr
  1775.         jc    IpRecKeepBuf
  1776. endif ; RFCC
  1777.         cmp    [di].iIpProt,ICMP_PROT    ; ICMP protocol?
  1778.         jne    IpNotIcmp
  1779.         jmp    IpRecIcmp
  1780.   IpNotIcmp:
  1781.         cmp    [di].iIpProt,UDP_PROT    ; UDP protocol?
  1782.         jne    IpProtUnr
  1783.  
  1784.         call    UdpChkSum        ; if available, test 
  1785.         jne    IpRecRet        ;   UDP checksum
  1786.  
  1787.         cmp    si,[bx].dPktEnd     ; still within packet limit?
  1788.         jbe    IpRecUdp
  1789.   IpRecRet:
  1790.         call    BufRelease        ; release receive buffer
  1791.   IPRecKeepBuf:
  1792. if DEBUG
  1793.         inc    DbgIntCnt
  1794. endif ; DEBUG
  1795.         cli                ; restore previous stack
  1796.         mov    sp, word ptr SaveSP
  1797.         mov    ss, word ptr SaveSS
  1798.         pop    ds
  1799.         popf
  1800.         retf
  1801.  
  1802.  
  1803.   IpPortUnr:
  1804.         mov    ah,3            ; port unreachable
  1805.         jmp    short IpUnr
  1806.   IpProtUnr:
  1807.         mov    ah,2            ; protocol unreachable
  1808.   IpUnr:
  1809. if RFCC
  1810.         mov    al,3            ; destination unreachable
  1811.  
  1812.         cmp    [bx].dIdxHwDst,ARPMYIDX ; was it specifically to me?
  1813.         jne    IpRecRet
  1814.  
  1815.         mov    bp,bx
  1816.         call    BufAlloc
  1817.         jz    UnrEnd
  1818.         call    MakeSendDescr
  1819.         mov    si,[bp].dPtrIp        ; copy IP header
  1820.         mov    cx,[bp].dPtrUdp
  1821.         add    cx,8            ;   + 8 bytes
  1822.         sub    cx,si
  1823.  
  1824.         call    SwitchIpDstB        ; return to sender
  1825.  
  1826.         mov    di,[bx].dPtrUdp
  1827.         mov    [di].uIcmpTypecode,ax    ; set type and code
  1828.  
  1829.         add    di,8
  1830.         call    movemem
  1831.  
  1832.         sub    di,[bx].dPtrUdp
  1833.         mov    [bx].dPktLen,di     ; set IP data length
  1834.  
  1835.         mov    si,offset IcmpToDo    ; put buf on the ICMP send list
  1836.         call    AddToList
  1837.   UnrEnd:
  1838.         mov    bx,bp
  1839. endif ; RFCC
  1840.         jmp    IpRecRet
  1841.  
  1842.  
  1843.   IpRecUdp:
  1844.         mov    [bx].dPktEnd,si         ; end of logical pkt
  1845.  
  1846.         mov    di,[bx].dPtrUdp
  1847.         cmp    word ptr [di].uUdpSrc,2500h    ; Src port 0025 = 37 ?
  1848.         je    IpRecvTime            ; - must be time reply
  1849. if TBLBUILD or PINGCLIENT
  1850.         cmp    word ptr [di].uUdpSrc,3500h    ; Name server (53)?
  1851.         jne    $+5
  1852.         jmp    IpRecvName
  1853. endif ; TBLBUILD or PINGCLIENT
  1854.         cmp    word ptr [di].uUdpSrc,4300h    ; Src port 0043 = 67
  1855.         jne    IpPortUnr
  1856.  
  1857.         cmp    word ptr [di].uUdpDst,4400h    ; Dst port 0044 = 68
  1858.         jne    IpPortUnr
  1859.  
  1860.         cmp    byte ptr [di].uBotOp,2    ; bootp reply?
  1861.         jne    IpRecRet
  1862.   IpRecBootp:
  1863.         push    di            ; - must be bootp reply
  1864.         lea    si,[di].uBotCliHwAd
  1865.         mov    di,offset MyHwAd
  1866.         mov    cx,Hlen
  1867.         repe    cmpsb            ; our Ethernet addr?
  1868.         pop    di
  1869.         jne    IpRecRet2
  1870.  
  1871.         mov    ax,word ptr IpDesBuf.fBotStruc.uBotXid  
  1872.         cmp    ax,word ptr [di].uBotXid    ; our random id?
  1873.         jne    IpRecRet2
  1874.         mov    ax,word ptr IpDesBuf.fBotStruc.uBotXid+2
  1875.         cmp    ax,word ptr [di].uBotXid+2
  1876.         jne    IpRecRet2
  1877.                         ; yes, it's about me!
  1878.         mov    dx,[di].uBotGwyIp    ; saves an ARP request
  1879.         mov    ax,[di].uBotGwyIp+2    ;   in many cases
  1880.         mov    si,[bx].dPtrPhys
  1881.         add    si,Hlen
  1882.         call    ArpPutNew
  1883.  
  1884.         test    Events,GOT_BOOTP    ; if first answer
  1885.         jnz    IpRecRet2        ;   save bootp answer
  1886.  
  1887.         mov    AdrBootpReply,bx    ;   for further study 
  1888.         or    Events,GOT_BOOTP
  1889.         jmp    IpRecKeepBuf
  1890.  
  1891.   IpRecvTime:
  1892.         test    Events,GOT_TIMEREPLY    ; already got reply?
  1893.         jnz    IpRecRet2
  1894.  
  1895.         mov    ax,[di].uUdpData    ; save seconds
  1896.         mov    cTime,ax        ;   since year 1900
  1897.         mov    ax,[di].uUdpData+2
  1898.         mov    cTime+2,ax
  1899.  
  1900.         mov    di,[bx].dPtrIp        ; save who was answering
  1901.         mov    dx,[di].iIpSrc
  1902.         mov    ax,[di].iIpSrc+2
  1903.         mov    RespondingIpNr,dx
  1904.         mov    RespondingIpNr+2,ax
  1905.         or    Events,GOT_TIMEREPLY
  1906.   IpRecRet2:
  1907.         jmp    IpRecRet
  1908.  
  1909. if TBLBUILD or PINGCLIENT
  1910.   IpRecvName:
  1911.         mov    si,offset NameToDo    ; process nameserver reply
  1912.         call    AddToList
  1913.         jmp    IpRecKeepBuf
  1914. endif ; TBLBUILD or PINGCLIENT
  1915.  
  1916.  
  1917.   IpRecIcmp:
  1918.         mov    cx,[di].iIpLen        ; calculate IP data length
  1919.         xchg    ch,cl
  1920.         add    cx,di
  1921.         sub    cx,si
  1922.         mov    [bx].dPktLen,cx     ; save IP data length
  1923.  
  1924.         call    SwitchIpDst        ; in case we want to return it
  1925.  
  1926.         call    IcmpChkSum        ; valid ICMP checksum?
  1927.         jne    IpRecRet2
  1928.  
  1929.         mov    si,[bx].dPtrUdp     ; point to ICMP header
  1930.         mov    cx,[si].uIcmpTypecode    ; get type and code
  1931.         mov    dx,[si].uIcmpIpHdr.iIpDst    ; get original IP hdr
  1932.         mov    ax,[si].uIcmpIpHdr.iIpDst+2    ;   dst IP #
  1933.  
  1934. if PINGCLIENT
  1935.         cmp    cl,0            ; echo reply?
  1936.         jne    IpNotEchoReply
  1937.         call    EchoCalc
  1938.         jmp    IpRecRet
  1939. endif ; PINGCLIENT
  1940.  
  1941. if RFCC
  1942.   IpNotEchoReply:
  1943.         cmp    cl,8            ; echo request?
  1944.         jne    IpNotEchoReq
  1945.  
  1946.         cmp    [bx].dIdxHwDst,ARPMYIDX ; broadcast?
  1947.         jb    IpRecRet2        ; - yes, don't echo
  1948.  
  1949.         mov    byte ptr [si].uIcmpTypecode,0 ; put echo reply value
  1950.  
  1951.         mov    si,offset IcmpToDo    ; put buf on the ICMP send list
  1952.         call    AddToList
  1953.         jmp    IpRecKeepBuf
  1954.  
  1955.   IpNotEchoReq:
  1956. endif ; RFCC
  1957.  
  1958.         cmp    cx,11            ; TTL exceeded?
  1959.         je    IpIcmpUnreach
  1960.  
  1961.         cmp    cl,3            ; unreachable
  1962.         jne    IpNotUnreach
  1963.  
  1964.         cmp    ch,12            ; net or host unreachable?
  1965.         ja    IpIcmpRet2
  1966.         cmp    ch,6
  1967.         ja    IpIcmpUnreach
  1968.         cmp    ch,1
  1969.         ja    IpIcmpRet2
  1970.   IpIcmpUnreach:                ; codes 0 - 1, 6 - 12 go here
  1971.         PushfDI
  1972.         push    si
  1973.         mov    cl,[si].uIcmpIpHdr.iIpTos
  1974.         xor    ch,ch
  1975.         mov    si,cx
  1976.         call    RouteFind        ; this host in route table?
  1977.         pop    si
  1978.         jnz    IpIcmpUnfound
  1979.  
  1980.         mov    ah,byte ptr [si].uIcmpTypeCode+1 ; icmp code
  1981.         xor    al,al        ;*test
  1982.         inc    ah            ; ensure non zero error code
  1983.         mov    RouteTabUnreach[di],ax    ; mark it unreachable
  1984.  
  1985.         call    CurrentTicks        ; get current ticks value
  1986.         mov    RouteTabTrRx[di],cx    ; set timer
  1987.   IpIcmpUnfound:
  1988.         PopfEI
  1989.   IpIcmpRet2:
  1990.         jmp    IpIcmpRet
  1991.  
  1992.   IpNotUnreach:
  1993. if RFCC
  1994.         cmp    cl,4            ; source quench
  1995.         jne    IpIcmpNotQuench
  1996.  
  1997.         PushfDI
  1998.         push    si
  1999.         mov    cl,[si].uIcmpIpHdr.iIpTos
  2000.         xor    ch,ch
  2001.         mov    si,cx
  2002.         call    RouteFind        ; this host in route table?
  2003.         pop    si
  2004.         jnz    IpIcmpNotRoute
  2005.  
  2006.         mov    dx,RouteTabFlags[di]
  2007.         or    RouteTabFlags[di],SQ_UPDATED
  2008.         lea    si,RouteTabTrSq[di]
  2009.         lea    di,RouteTabSqDelay[di]
  2010.         jmp    short IpIcmpSq
  2011.   IpIcmpNotRoute:
  2012.         call    ArpFindIp
  2013.         jnz    IpIcmpSqEnd
  2014.  
  2015.         mov    dx,ArpTabFlags[di]
  2016.         or    ArpTabFlags[di],SQ_UPDATED
  2017.         lea    si,ArpTabTrSq[di]
  2018.         lea    di,ArpTabSqDelay[di]
  2019.   IpIcmpSq:
  2020.         mov    ax,[di]         ; get current sq delay
  2021.         or    ax,ax
  2022.         jnz    IpIcmpAddDelay
  2023.         call    CurrentTicks
  2024.         mov    [si],cx         ; initialize sq timer
  2025.         mov    ax,150*64/55        ; initial sq delay 178 ms
  2026.   IpIcmpAddDelay:
  2027.         add    ax,28*64/55        ; increase delay by 28 ms
  2028.         test    dx,SQ_UPDATED        ;   unless already done in
  2029.         jnz    IpIcmpSqEnd        ;   the last two seconds
  2030.         mov    [di],ax
  2031.   IpIcmpSqEnd:
  2032.         PopfEI
  2033.         jmp    short IpIcmpRet
  2034.  
  2035.   IpIcmpNotQuench:
  2036. endif ; RFCC
  2037.         cmp    cl,5            ; redirect
  2038.         jne    IpNotRedirect
  2039.  
  2040.         PushfDI
  2041.         push    si
  2042.         mov    cl,[si].uIcmpIpHdr.iIpTos
  2043.         xor    ch,ch
  2044.         mov    si,cx
  2045.         call    RouteFind        ; this host in route table?
  2046.         pop    si
  2047.         jnz    IpIcmpDisfound
  2048.  
  2049.         mov    dx,RouteTabIpG1[di]    ; icmp from the gwy used?
  2050.         mov    ax,RouteTabIpG2[di]
  2051.         mov    cx,di
  2052.         mov    di,[bx].dPtrIp
  2053.         cmp    dx,[di].iIpSrc
  2054.         jne    IpIcmpDisfound
  2055.         cmp    ax,[di].iIpSrc+2
  2056.         jne    IpIcmpDisfound
  2057.         mov    di,cx
  2058.  
  2059.         mov    dx,[si].uIcmpData    ; new gateway IP #
  2060.         mov    ax,[si].uIcmpData+2
  2061.  
  2062.         call    MyNetChk        ; is he on my net?
  2063.         jnz    IpIcmpDisfound
  2064.  
  2065.         mov    RouteTabIpG1[di],dx    ; put it into route table
  2066.         mov    RouteTabIpG2[di],ax
  2067.   IpIcmpDisfound:
  2068.         PopfEI
  2069.         jmp    short IpIcmpRet
  2070.  
  2071.   IpNotRedirect:
  2072.   IpIcmpRet:
  2073.         jmp    IpRecRet
  2074.  
  2075.  
  2076. ;************************************************************************
  2077. ;*        MakeMynet
  2078. ;************************************************************************
  2079.  
  2080. MakeMynet    proc    near
  2081.         mov    dx,MyIpNr
  2082.         mov    ax,MyIpNr+2
  2083.  
  2084.         mov    ArpTabIp1+4,dx        ; third arp slot = me
  2085.         mov    ArpTabIp2+4,ax
  2086.         mov    si,offset MyHwAd
  2087.         call    ArpPutNew
  2088.  
  2089.         mov    si,MyMask
  2090.         mov    di,MyMask+2
  2091.         and    dx,si            ; calculate network #
  2092.         and    ax,di
  2093.         mov    MyNet,dx
  2094.         mov    MyNet+2,ax
  2095.  
  2096.         not    si            ; second arp slot =
  2097.         not    di            ;   subnet broadcast
  2098.         or    dx,si
  2099.         or    ax,di
  2100.         mov    ArpTabIp1+2,dx
  2101.         mov    ArpTabIp2+2,ax
  2102.         ret
  2103. MakeMynet    endp
  2104.  
  2105.  
  2106.  
  2107. ;************************************************************************
  2108. ;*        ValidateIpNr
  2109. ;************************************************************************
  2110.  
  2111. ValidateIpNr    proc    near
  2112.         call    BufAlloc
  2113.  
  2114.         mov    [bx].dTimOutMsg,0    ; we SHOULD get no answer
  2115.         mov    [bx].dTickTimeout,10    ; give them half a second
  2116.         mov    dx,MyIpNr
  2117.         mov    ax,MyIpNr+2
  2118.         call    SendArpReq        ; send arp to our Ip #
  2119.         call    BufRelease
  2120.         jz    ValConflict        ; someone else has our IP # ?
  2121.  
  2122.         ret                ; - no, return
  2123.  
  2124.   ValConflict:                    ; - yes, error termination
  2125.         call    ArpFindIp
  2126.         mov    cl,3
  2127.         shl    di,cl
  2128.         lea    si,ArpTabHwAdr[di]    ; get HW addr of arp reply
  2129.  
  2130.         mov    di,offset OccupiedHw
  2131.         call    PutHwNum        ; put offending HW addr
  2132.  
  2133.         mov    dx,offset OccupiedMsg    ; display IP occupied msg
  2134.         mov    ah,9
  2135.         int    21h
  2136.  
  2137.         mov    al,09            ; error code 9
  2138.         call    terminate
  2139. ValidateIpNr    endp
  2140.  
  2141.  
  2142.  
  2143. ;************************************************************************
  2144. ;*        DoBootpPkt
  2145. ;************************************************************************
  2146.  
  2147. DoBootpPkt    proc    near
  2148.         call    CurrentTicks        ; get current ticks value
  2149.         mov    IpDesBuf.fBotStruc.uBotXid,cx    ;   as transaction id
  2150. if RFCC
  2151.         add    cx,2*18         ; initialize ageing
  2152.         mov    AgeNext,cx
  2153.         mov    AgeFragsNext,cx
  2154. endif ; RFCC
  2155.         mov    al,byte ptr ArpBuf.iArpHtype+1
  2156.         mov    IpDesBuf.fBotStruc.uBotHtype,al ; put my HW type
  2157.  
  2158.         mov    si,offset MyHwAd
  2159.         mov    di,offset IpDesBuf.fBotStruc.uBotCliHwAd
  2160.         push    cs
  2161.         pop    es
  2162.         mov    cx,Hlen
  2163.         mov    IpDesBuf.fBotStruc.uBotHlen,cl
  2164.         rep    movsb                ; copy my HW addr
  2165.  
  2166.         mov    bx,offset IpDesBuf        ; frame to send
  2167.         call    MakeSendDescr
  2168.         mov    [bx].dWaitEvent,GOT_BOOTP    ; event to wait for
  2169.         mov    [bx].dTimOutMsg,offset NoBotReplyMsg ; error msg
  2170.         mov    ax,BpDataLen+UDPHDRLEN        ; bootp pkt length
  2171.         call    SendUdpPkt            ; send bootp request
  2172.  
  2173.         ret
  2174. DoBootpPkt    endp
  2175.  
  2176.  
  2177.  
  2178. ;************************************************************************
  2179. ;*        InterpBootp according to RFC 1084 and RFC1048
  2180. ;************************************************************************
  2181.  
  2182. InterpBootp    proc    near
  2183.         mov    bx,AdrBootpReply
  2184.         mov    di,[bx].dPtrUdp
  2185.         mov    dx,[di].uBotYourIp    ; mov my IP #
  2186.         mov    MyIpNr,dx        ;   to IP buf
  2187.         mov    ax,[di].uBotYourIp+2
  2188.         mov    MyIpNr+2,ax
  2189.  
  2190.         or    Flagword,HAVE_MYIPNR    ; note what we've got
  2191.  
  2192.         cmp    word ptr [di].uBotMagNum,8263h    ; RFC 1084 type of
  2193.         jne    VendEnd             ;   vendor area?
  2194.         cmp    word ptr [di].uBotMagNum+2,6353h
  2195.         jne    VendEnd
  2196.  
  2197.         lea    si,[di].uBotVend    ; start of "vendor area"
  2198.         lea    bp,[si]+64-4        ; end of "vendor area"
  2199.         push    cs
  2200.         pop    es
  2201.   VendLoop:
  2202.         cmp    si,bp            ; beyond vendor area?
  2203.         jb    VendNext
  2204.  
  2205.   VendEnd:
  2206.         call    BufRelease        ; release bootp reply buf
  2207.         ret
  2208.  
  2209.   VendNext:
  2210.         lodsb                ; get field type:
  2211.  
  2212.         cmp    al,0            ; filler
  2213.         je    VendLoop
  2214.  
  2215.         cmp    al,1            ; netmask
  2216.         jne    NotMask
  2217.         mov    di,offset MyMask
  2218.         call    Xtract4Bytes
  2219.         jmp    short VendLoop
  2220.   NotMask:
  2221.         cmp    al,2            ; zone/time (?) offset
  2222.         jne    NotTimeOffs
  2223.         test    Flagword,HAVE_TIMEOFFSET
  2224.         jnz    VendDefault
  2225.         mov    di,offset tzoffset
  2226.         call    Xtract4Bytes
  2227.         or    Flagword,HAVE_TIMEOFFSET
  2228.         jmp    short VendLoop
  2229.   NotTimeOffs:
  2230.         cmp    al,3            ; default gateways
  2231.         jne    NotDefGwys
  2232.         mov    di,offset DefGwys
  2233.         mov    cx,MAXDEFGWYS
  2234.         mov    ax,DefGwyNum
  2235.         call    XtractIpNums
  2236.         add    DefGwyNum,cx
  2237.         jmp    short VendLoop
  2238.   NotDefGwys:
  2239.         cmp    al,4            ; time servers
  2240.         jne    NotTimeserv
  2241.         or    Flagword,HAVE_TIMESERVER
  2242.         mov    di,offset TimeServIpNr
  2243.         mov    cx,MAXTSERVS
  2244.         mov    ax,TservNum
  2245.         call    XtractIpNums
  2246.         add    TservNum,cx
  2247.         jmp    short VendLoop
  2248.   NotTimeserv:
  2249. if TBLBUILD or PINGCLIENT
  2250.         cmp    al,6            ; default nameservers
  2251.         jne    NotDefNS
  2252.         mov    di,offset DefNS
  2253.         mov    cx,MAXDEFNS
  2254.         mov    ax,DefNSnum
  2255.         call    XtractIpNums
  2256.         add    DefNSnum,cx
  2257.         jmp    short VendLoop
  2258.   NotDefNS:
  2259. endif ; TBLBUILD or PINGCLIENT
  2260.         cmp    al,0ffh         ; end
  2261.         je    VendEnd
  2262.   VendDefault:                    ; everything else
  2263.         lodsb
  2264.         xor    ah,ah
  2265.         add    si,ax            ; skip field
  2266.         jmp    Vendloop
  2267.  
  2268. InterpBootp    endp
  2269.  
  2270.  
  2271.  
  2272. ;************************************************************************
  2273. ;*        XtractIpNums
  2274. ;************************************************************************
  2275.  
  2276. XtractIpNums    proc    near
  2277.         sub    cx,ax            ; wanted - already got
  2278.  
  2279.         shl    ax,1
  2280.         shl    ax,1
  2281.         add    di,ax            ; append to what we got
  2282.         shl    cx,1
  2283.         shl    cx,1
  2284.         jmp    short XtractNBytes
  2285. Xtract4Bytes:
  2286.         mov    cl,4
  2287. XtractNBytes:
  2288.         lodsb
  2289.         cmp    cl,al            ; as many as we want?
  2290.         jbe    XtractOkLen
  2291.  
  2292.         mov    cl,al            ; - no, take what there is
  2293.   XtractOkLen:
  2294.         xor    ch,ch
  2295.         xor    ah,ah
  2296.         push    cx
  2297.         push    ax
  2298.         push    si
  2299.         rep    movsb            ; copy field
  2300.         pop    si
  2301.  
  2302.         pop    ax
  2303.         add    si,ax            ; advance field ptr
  2304.  
  2305.         pop    cx
  2306.         shr    cx,1
  2307.         shr    cx,1            ; cx = IP #'s read
  2308.  
  2309.         ret
  2310. XtractIpNums    endp
  2311.  
  2312. ;========================================================================
  2313. ;        endinclude
  2314.